﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EC3_6CLH.Model
{
    public class InitParam
    {
        public string Name { get; set; }

        //public UInt16 Axis => UInt16.Parse(Name.Substring(0, Name.IndexOf("轴")));
        public const UInt16 Axis = 1;

        public UInt16 Index { get; set; }
        public UInt16 SubIndex { get; set; }
        public string Type { get; set; }
        public Int16 TypeValue => GetDataType(Type);

        public UInt16 DataLen => GetDataLen(Type);
        public string Data { get; set; }
        public object DataValue => GetValueByType(Data, Type);

        private bool AreEqual(float a, float b, int decimalPlaces = 5)
        {
            // 先计算差值
            float diff = MathF.Abs(a - b);

            // 计算允许的误差（例如保留 5 位小数，则 epsilon = 0.00001）
            float epsilon = MathF.Pow(10, -decimalPlaces);

            return diff < epsilon;
        }

        private int GetDecimalPlaces(float number)
        {
            string numStr = number.ToString(System.Globalization.CultureInfo.InvariantCulture);

            // 检查是否有小数点
            int decimalPointIndex = numStr.IndexOf('.');
            if (decimalPointIndex == -1)
            {
                return 0; // 没有小数部分
            }

            // 提取小数部分并计算位数
            string decimalPart = numStr.Substring(decimalPointIndex + 1);
            return decimalPart.Length;
        }

        public bool AreEqual(object value)
        {
            if (true)
            {
                switch (Type)
                {
                    case "U16":
                    case "I8":
                    case "I16":
                    case "U8 ":
                    case "U32":
                    case "I32":
                        return value.Equals(DataValue);

                    case "F32":
                        if (value is float tmp)
                        {
                            var tmp0 = (float)DataValue;
                            return AreEqual(tmp0, tmp, GetDecimalPlaces(tmp0));
                        }
                        else
                        {
                            throw new Exception($"expected {DataValue.GetType().Name} but {value.GetType().Name}");
                        }

                    default:
                        throw new Exception($"无效的数据类型");
                }
            }
        }

        public static UInt16 GetDataLen(string type)
        {
            UInt16 len = 0;
            switch (type)
            {
                case "U16":
                    len=1;
                    break;

                case "F32":
                    len=2;
                    break;

                case "I8":
                    len=1;
                    break;

                case "I16":
                    len=1;
                    break;

                case "U8 ":
                    len=1;
                    break;

                case "U32":
                    len=2;
                    break;

                case "I32":
                    len=2;
                    break;

                default:
                    break;
            }
            return len;
        }

        public static Int16 GetDataType(string type)
        {
            Int16 typeValue = 0;
            switch (type)
            {
                case "U16":
                    typeValue=2;
                    break;

                case "F32":
                    typeValue=5;
                    break;

                case "I8":
                    typeValue=-1;
                    break;

                case "I16":
                    typeValue=-2;
                    break;

                case "U8 ":
                    typeValue=1;
                    break;

                case "U32":
                    typeValue=4;
                    break;

                case "I32":
                    typeValue=-4;
                    break;

                default:
                    break;
            }
            return typeValue;
        }

        public static object GetValueByType(string data, string type)
        {
            object convertedData;
            switch (type)
            {
                case "U16":
                    convertedData = UInt16.Parse(data);
                    break;

                case "F32":
                    convertedData = float.Parse(data);
                    break;

                case "I8":
                    convertedData = sbyte.Parse(data);
                    break;

                case "I16":
                    convertedData = Int16.Parse(data);
                    break;

                case "U8 ":
                    convertedData = byte.Parse(data);
                    break;

                case "U32":
                    convertedData = UInt32.Parse(data);
                    break;

                case "I32":
                    convertedData = Int32.Parse(data);
                    break;

                default:
                    convertedData = null;
                    break;
            }
            return convertedData;
        }
    }
}